import requests
import random
import re
import time
import js2py
import json
from random import choice
import datetime
from requests.adapters import HTTPAdapter
from utils.common import http_session
from enums.sys_type_enum import SysTypeEnum
import traceback
from exception.api_exception import APIException


class IpProxy(object):
    def __init__(self, region):
        self.sessions = http_session.get_global_session()
        self.region = region

    # 通过请求星速代理服务器获取代理IP
    def get_proxy_ip(self, server_url):
        # server_resp = requests.session().get(server_url, verify=False)
        tries = 3
        for cur_try in range(tries):
            try:
                server_resp = self.sessions.get(server_url, verify=False)
                if not server_resp:
                    print("获取server_resp失败")
                    raise Exception
                proxy_resp = json.loads(server_resp.text)
                if proxy_resp["code"] == 200:
                    ip_list = proxy_resp["result"]
                    if len(ip_list) <= 0:
                        print("获取的代理ip_list为空")
                        raise Exception
                    # 随机返回一个代理IP信息
                    return choice(ip_list)
            except Exception as e:
                if cur_try < tries - 1:
                    continue
                else:
                    traceback.print_exc()
                    print("获取代理IP失败")
            break

    # 解析json格式的请求行
    def parse_ip(self, server_url):
        one_proxy_ip_line = self.get_proxy_ip(server_url)

        if one_proxy_ip_line is None:
            print('获取代理信息为空')
            return None, None, '获取代理信息为空'

        line_list = one_proxy_ip_line.split(",")
        ip_port = line_list[0].split(":")
        ip = ip_port[0]
        port = ip_port[1]
        return ip, port, one_proxy_ip_line

    def get_ip_proxy(self):
        cur_region = self.region
        xingsudailiUrl = "http://user.xingsudaili.com:25434/jeecg-boot/extractIp/s?" \
                         "uid=1696404251663200258&" \
                         "orderNumber=CN2023082915360319&" \
                         "number=1&" \
                         "wt=json&" \
                         "randomFlag=false&" \
                         "detailFlag=true&" \
                         "useTime=150&" \
                         "region=" + cur_region

        # 获取代理服务器ip和端口
        proxyHost, proxyPort, one_proxy_ip_line = self.parse_ip(xingsudailiUrl)

        if proxyHost is None or proxyPort is None:
            raise Exception("无法从星速代理服务器获取代理IP，请稍后重试！")
        print("代理ip和代理端口：", proxyHost, proxyPort)

        proxy_username = 'proxy_user'  # (产品管理-白名单&账密验证-用户名/密码 获取)
        proxy_pwd = 'proxy_password'  # (产品管理-白名单&账密验证-用户名/密码 获取)

        proxyMeta = "http://%(user)s:%(pass)s@%(host)s:%(port)s" % {
            "host": proxyHost,
            "port": proxyPort,
            "user": proxy_username,
            "pass": proxy_pwd,
        }

        proxies = {
            "http": proxyMeta,
            "https": proxyMeta
        }
        return proxies, one_proxy_ip_line


class QuestionareSpider(object):

    def __init__(self, id, proxy_obj):
        self.sessions = http_session.get_global_session()
        self.proxy_obj = proxy_obj
        self.shortId = id
        self.headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36",
        }

    def get_jqsign(self, ktimes: int, jqnonce: str):
        result = []
        b = ktimes % 10 if ktimes % 10 != 0 else 1
        for char in list(jqnonce):
            f = ord(char) ^ b
            result.append(chr(f))
        return ''.join(result)

    def get_jqpraram(self, rndnum, activityId, starttime):
        with open('./js_file/questionare_.js', 'r', encoding='utf8') as f:
            script = f.read()
        context = js2py.EvalJs(enable_require=True)
        context.execute(script)
        ts = int(time.mktime(time.strptime(starttime, "%Y/%m/%d %H:%M:%S")))
        # print(context._0x156205('988609781.60866459', 1689348352, '22****20'))
        return context._0x156205(rndnum, ts, activityId)

    def get_cookies(self):
        self.headers[
            'X-Forwarded-For'] = f'{112}.{random.randint(64, 68)}.{random.randint(0, 255)}.{random.randint(0, 255)}'
        response = self.sessions.get('https://www.wjx.cn/vm/' + self.shortId + '.aspx', headers=self.headers,
                                     timeout=10, verify=False)
        # self.sessions.get("https://image.wjx.cn/js/plugin/jquery-viewer.js?v=3219", headers=self.headers, timeout=10,
        #                   proxies=self.proxy_obj)
        # res2 = self.sessions.get('https://ynuf.aliapp.org/w/wu.json', headers=self.headers, timeout=10,
        #                          proxies=self.proxy_obj)
        # self.sessions.cookies.update({
        #     'ssxmod_itna': 'Qq0xyWK7qYqq2Dl4iwlEYGCIG8KN6Eo43D7W+zDBMhd4iNDnD8x7YDv+I5dw73O0Enxa45mRw4aeWQrcAxfi0hphaN3g+reDHxY=DU=7doDx1q0rD74irDDxD3Db4QDSDWKD9D0+kSBuqtDm4GWCqGfDDoDYR=nDitD4qDB+2dDKqGgCLhbCkrXzlUdLkGPsBxyD0UQxBdt8cuo1P9bSkrTrpiaiqGySPGuRMtVDMbDCoUVnwisC+ho+A5KYo3YQDAQYGGhi+qN/0DKt44f5GwKW0PoSE1DG4d9TrD=='
        # })
        # self.sessions.cookies.update({
        #     'ssxmod_itna2': 'Qq0xyWK7qYqq2Dl4iwlEYGCIG8KN6Eo43D7WD8q10AnDGNI3Gaz70IoBQGx8gOFNKcWlSyjbulxQgbm3=4lBpANsWRB0Eqf9laRw/n4miHA5vRgkiG0DT9COn6LzWUWSuNNtHZhNWTAGKRoMfqtnYl0/eQjcelt9GS=KOSQlfWbyme05vAeGjEQ31BrG3BrKD1KKB+Rto=qTvEwOk19=TkF75jN0WptE/T6HoFuH0CnvWz3404u8T47F=iOG3=EmSCf8QtWXMz6EsBxHs8uxIhpfI/9jXmcbK4+5FdWv6H1jzyoSnIaup5dO68QhcA6QWeEEtqDtz1fZZej238E08n=77ExljpZ+nE=cQhv0pnxeq/2/0huZ4qC2QKf/DY3IrrImRlGQQu7lXRDhaRDa8u7nbhU2a8n++bqG4DQKFD08DijbYD=='})
        # print(f'参数的含义暂时未知：{res2.content.decode()}')
        # # 经过几次发送验证码抓包对比，发现data开头的106!这几个字符是固定的。106!后面随意拼接字符都可以正常取到token
        # rand_str = 'GwWKhOu41p50+P3j7ad9FmtEMZ/8oVHYJicCg6fbLqAkyBxQX=Rl2erUvDInzTSsN'
        # randtumple = (rand_str[random.randrange(0, len(rand_str))] for i in range(0, 570))
        # string = ''.join(randtumple)
        # data = {'data': "107!" + string + '==', "xa": "FFFF00000000016770EE", "xt": "", "efy": 1}
        # res3 = self.sessions.post('https://ynuf.aliapp.org/service/um.json', headers=self.headers, data=data,
        #                           timeout=10, proxies=self.proxy_obj)
        # print(f"id:{res3.json()['id']}")
        # print(f'tn:{res3.json()["tn"]}')
        # print(self.sessions.cookies.items())
        return response.content.decode()

    def get_params(self, content):
        # ktimes 为鼠标移动次数
        ktimes = random.randint(57, 143) + int(random.random() * 286)
        jqnonce = re.search(r'.{8}-.{4}-.{4}-.{4}-.{12}', content).group()
        rndnum = re.search(r'\d{9,10}\.\d{8}', content).group()
        start_time = re.search(r'\d+?/\d+?/\d+?\s\d+?:\d{2}:\d{2}', content).group()
        activityId = re.search(r'activityId =(\d+);', content).group(1)
        activityId = int(activityId) ^ 2130030173
        params = {
            'shortid': self.shortId,
            'starttime': start_time,
            'submittype': 1,
            'ktimes': ktimes,
            'hlv': 1,
            'rn': rndnum,
            'jqpram': self.get_jqpraram(rndnum, str(activityId), start_time),
            'nw': '1',
            'jwt': '4',
            'jpm': '83',
            't': int(time.time() * 1000),
            'jqnonce': jqnonce,
            'jqsign': self.get_jqsign(ktimes, jqnonce),
        }
        return activityId, params

    def submit(self, submitdata, sleeptime: int):
        """
        提交问卷
        :param submitdata: 需要提交数据
        :param sleeptime: 提交的间隔时间
        :return:
        """

        starttime = datetime.datetime.now()
        content = self.get_cookies()
        print('睡', sleeptime, '秒再开始发送')
        time.sleep(sleeptime)
        print('请求-1的时间', (datetime.datetime.now() - starttime).seconds)
        params = self.get_params(content)
        self.headers.pop('X-Forwarded-For')
        url = "https://www.wjx.cn/joinnew/processjq.ashx"
        data = {'submitdata': submitdata}
        print('请求0的时间', (datetime.datetime.now() - starttime).seconds)
        # self.sessions.get('https://image.wjx.cn/images/wjxMobile/wait.gif', headers=self.headers, timeout=10,
        #                   proxies=self.proxy_obj)
        print('请求1的时间', (datetime.datetime.now() - starttime).seconds)
        self.headers["Connection"] = 'close'  # 关闭长链接
        self.headers['Origin'] = 'https://www.wjx.cn'
        self.headers["Host"] = 'www.wjx.cn'
        self.headers['X-Requested-With'] = 'XMLHttpRequest'
        self.headers["Referer"] = 'https://www.wjx.cn/vm/h4IsOBH.aspx'
        # playload = {"APIVersion": "0.6.0", "a": params[0], 'pd': data['submitdata']}
        # self.sessions.get("https://sojump.cn-hangzhou.log.aliyuncs.com/logstores/activitypostdata/track.gif",
        #                   params=playload, headers=self.headers, timeout=10, proxies=self.proxy_obj)
        print('请求2的时间', (datetime.datetime.now() - starttime).seconds)
        res = self.sessions.post(url, headers=self.headers, params=params[1], data=data, timeout=10,
                                 proxies=self.proxy_obj, verify=False)
        print('请求3的时间', (datetime.datetime.now() - starttime).seconds)
        pd = res.content.decode()
        # playload2 = {"APIVersion": "0.6.0", "a": params[0], 'pd': pd}
        # self.sessions.get('https://sojump.cn-hangzhou.log.aliyuncs.com/logstores/activitypostdata/track.gif',
        #                   headers=self.headers, timeout=10, params=playload2, proxies=self.proxy_obj)
        # finish_url = f'https://sojump.cn-hangzhou.log.aliyuncs.com/logstores/activityfinish/track.gif?APIVersion=0.6.0&activity={params[0]}&source=1&weixin=0&vip=0&qtype=1&qw=0&name=BMvL05bbhlcmCLd4yzLerQ%3D%3D'
        # self.sessions.get(finish_url, headers=self.headers, timeout=10, proxies=self.proxy_obj)
        # refer = pd.split('?')[1]
        # https://www.wjx.cn/wjx/join/completemobile2.aspx?
        # activityid=h4IsOBH&joinactivity=118268349309&sojumpindex=11&tvd=4w0ngE1RduU%3d&comsign=748F2A7A0DF2A11D5BAC9440C58B59E14FFB3B75&ge=1&nw=1&jpm=83
        # activityid=h4IsOBH&joinid=118268349412&sojumpindex=12&tvd=4w0ngE1RduU%3d&comsign=7D5BE7DD2F5D8D5C4C5D3E2C829651B1A70D5E25&ge=1&nw=1&jpm=83
        return pd


def convert_data_to_submit_data(db_title_arr, db_res_arr) -> str:
    """
    将数据库中的数据转换为需要提交的结果数据
    :param db_title_arr: 题目与数据库结果的映射关系数组
    :param db_res_arr: 需要提交的答案数组
    :return:
    """
    res = ''
    for index in range(len(db_title_arr)):
        i = db_title_arr[index]
        indexes = i['data_index']
        cur_type = i['sys_type']
        s = i['title_id'] + '$'
        if len(indexes) > 1:
            if cur_type == SysTypeEnum.MULTIPLE.value:
                cur_s = ''
                for j in range(len(indexes)):
                    mu_arr = str(db_res_arr[indexes[j]]).split('^')
                    if mu_arr and mu_arr[0] == '1':  # 如果为1，表示需要提交这个选项
                        if cur_s != '':
                            cur_s += '|'
                        cur_s += str(j + 1)
                        if len(mu_arr) >= 2:
                            cur_s += '^' + str(mu_arr[1])
                s += cur_s
            elif cur_type == SysTypeEnum.MATRIX.value:
                for j in range(len(indexes)):
                    s += str(j + 1) + '!' + str(db_res_arr[indexes[j]])
                    if j < len(indexes) - 1:
                        s += ','
            elif cur_type == SysTypeEnum.SLIDE.value or cur_type == SysTypeEnum.RATE.value:
                for j in range(len(indexes)):
                    s += str(j + 1) + '!' + str(db_res_arr[indexes[j]])
                    if j > len(indexes) - 1:
                        s += '^'
            elif cur_type == SysTypeEnum.SORTED.value:
                for j in range(len(indexes)):
                    s += str(db_res_arr[indexes[j]])
                    if j < len(indexes) - 1:
                        s += ','
            else:
                for j in range(len(indexes)):
                    s += str(db_res_arr[indexes[j]])
        else:
            s += str(db_res_arr[indexes[0]])
        if index < len(db_title_arr) - 1:
            s += '}'
        res += s
    return res


def do_submit(proxy_region: str, url_title_id: str, submitdata: str, sleep_time: int):
    print('开始发送问卷')
    ip_o = IpProxy(region=proxy_region)
    print('开始获取代理ip')
    proxy_o, ip_res = ip_o.get_ip_proxy()  # 获取代理
    print('创建问卷对象')
    qo = QuestionareSpider(id=url_title_id, proxy_obj=proxy_o)  # 创建问卷对象
    print('发起提交')
    print(submitdata)
    res = qo.submit(submitdata, sleep_time)  # 提交
    return res, ip_res


if __name__ == '__main__':
    for i in range(1):
        ip_pro = IpProxy(region="")
        proxy_obj = ip_pro.get_ip_proxy()  # 获取代理
        title_rurl_id = 'r1XDjE0'
        qs = QuestionareSpider(id=title_rurl_id, proxy_obj=proxy_obj)  # 创建问卷对象
        submitdata = "1$3}2$3^x}3$1|2|3|4}4$1|2|3|4^x}5$1!71^2!54}6$2,1,3}7$2,1,3}8$1!90^2!10}9$北京-北京市-东城区}10$2}11$2}12$填空1}13$2023-08-27}14$1!5,2!4,3!5,4!5,5!3}15$1!5,2!5,3!5,4!3,5!5}16$1!40^2!99^3!63^4!63^5!51}17$2"
        sleeptime = random.randint(60, 120)
        print()
        print('需要', sleeptime, '秒后再提交')
        qs.submit(submitdata, sleeptime)
        time.sleep(random.random() * 20 + 10)
    exit()
